﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EnvDTE;
using System.IO;
using System.Runtime.Serialization;

namespace Perovich.GameObjects.Tools.Util
{
    [Serializable()]
    public class ProjectExt
    {
        private Project project;

        public ProjectExt(Project p)
        {
            this.project = p;
        }

        public CodeModel CodeModel
        {
            get
            {
                return project.CodeModel;
            }
        }

        public string RootNameSpace {
            get {
                return project.Properties.Item("RootNamespace").Value.ToString();
            }
        }

        public string Directory
        {
            get
            {
                return project.Properties.Item("FullPath").Value.ToString();
            }
        }


        //browseUrl is either the File Path or the Strong Name
        //(System.Configuration, Version=2.0.0.0, Culture=neutral,
        //                       PublicKeyToken=B03F5F7F11D50A3A)
        public void AddReference(string referenceStrIdentity, string browseUrl)
        {
            string path = "";

            if (!browseUrl.StartsWith(referenceStrIdentity))
            {
                //it is a path
                path = browseUrl;
            }


            if (project.Object is VSLangProj.VSProject)
            {
                VSLangProj.VSProject vsproject = (VSLangProj.VSProject)project.Object;
                VSLangProj.Reference reference = null;
                try
                {
                    reference = vsproject.References.Find(referenceStrIdentity);
                }
                catch (Exception ex)
                {
                    //it failed to find one, so it must not exist. 
                    //But it decided to error for the fun of it. :)
                }
                if (reference == null)
                {
                    if (path == "")
                    {
                        var r = vsproject.References.Add(browseUrl);
                    }
                    else
                        vsproject.References.Add(path);
                }
                else
                {
                    //throw new Exception("Reference already exists.");
                }
            }
            else if (project.Object is VsWebSite.VSWebSite)
            {
                VsWebSite.VSWebSite vswebsite = (VsWebSite.VSWebSite)project.Object;
                VsWebSite.AssemblyReference reference = null;
                try
                {
                    foreach (VsWebSite.AssemblyReference r in vswebsite.References)
                    {
                        if (r.Name == referenceStrIdentity)
                        {
                            reference = r;
                            break;
                        }
                    }
                }
                catch (Exception ex)
                {
                    //it failed to find one, so it must not exist. 
                    //But it decided to error for the fun of it. :)
                }
                if (reference == null)
                {
                    if (path == "")
                        vswebsite.References.AddFromGAC(browseUrl);
                    else
                        vswebsite.References.AddFromFile(path);

                }
                else
                {
                    throw new Exception("Reference already exists.");
                }
            }
            else
            {
                throw new Exception("Currently, system is only set up " +
                          "to do references for normal projects.");
            }
        }

        public List<KeyValuePair<string, string>> GetReferences()
        {
            List<KeyValuePair<string, string>> list =
                   new List<KeyValuePair<string, string>>();
            if (project.Object is VSLangProj.VSProject)
            {
                VSLangProj.VSProject vsproject = (VSLangProj.VSProject)project.Object;
                foreach (VSLangProj.Reference reference in vsproject.References)
                {
                    if (reference.StrongName)
                        //System.Configuration, Version=2.0.0.0,
                        //Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A
                        list.Add(new KeyValuePair<string, string>(reference.Identity,
                            reference.Identity +
                            ", Version=" + reference.Version +
                            ", Culture=" + (string.IsNullOrEmpty(reference.Culture) ?
                            "neutral" : reference.Culture) +
                            ", PublicKeyToken=" + reference.PublicKeyToken));
                    else
                        list.Add(new KeyValuePair<string, string>(
                                     reference.Identity, reference.Path));
                }
                return list;
            }
            else if (project.Object is VsWebSite.VSWebSite)
            {
                VsWebSite.VSWebSite vswebsite = (VsWebSite.VSWebSite)project.Object;
                foreach (VsWebSite.AssemblyReference reference in vswebsite.References)
                {
                    string value = "";
                    if (reference.FullPath != "")
                    {
                        FileInfo f = new FileInfo(reference.FullPath + ".refresh");
                        if (f.Exists)
                        {
                            using (FileStream stream = f.OpenRead())
                            {
                                using (StreamReader r = new StreamReader(stream))
                                {
                                    value = r.ReadToEnd().Trim();
                                }
                            }
                        }
                    }
                    if (value == "")
                    {
                        list.Add(new KeyValuePair<string, string>(reference.Name,
                                 reference.StrongName));
                    }
                    else
                    {
                        list.Add(new KeyValuePair<string, string>(reference.Name, value));
                    }
                }
                return list;
            }
            else
            {
                throw new Exception("Currently, system is only set up to " +
                                    "do references for normal projects.");
            }
        }



    }
}
